import os
import json
import logging
from datetime import datetime
from typing import Dict, Any

from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse, HttpResponse, Http404
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.core.paginator import Paginator
from django.core.files.storage import default_storage
from django.conf import settings
from django.utils.decorators import method_decorator
from django.views import View
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Count
from django.db import transaction

from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser

from .models import ProcessingTask, UploadedFile, Template
from .serializers import ProcessingTaskSerializer, UploadedFileSerializer, TemplateSerializer
from .services import data_processing_service, task_queue_service
from .utils import (
    generate_unique_filename, get_file_info, format_file_size,
    parse_file_filters, get_task_status_display, get_priority_display,
    sanitize_filename_for_download, get_file_preview_url
)

logger = logging.getLogger(__name__)

# ============ 页面视图 ============

@login_required
def dashboard(request):
    """仪表板页面"""
    try:
        # 获取统计数据
        task_stats = ProcessingTask.objects.filter(created_by=request.user).aggregate(
            total=Count('id'),
            pending=Count('id', filter=Q(status='pending')),
            processing=Count('id', filter=Q(status='processing')),
            completed=Count('id', filter=Q(status='completed')),
            failed=Count('id', filter=Q(status='failed'))
        )
        
        file_stats = UploadedFile.objects.aggregate(
            total=Count('id'),
            source_files=Count('id', filter=Q(file_type='source')),
            template_files=Count('id', filter=Q(file_type='template'))
        )
        
        template_stats = Template.objects.aggregate(
            total=Count('id')
        )
        
        # 最近任务
        recent_tasks = ProcessingTask.objects.filter(
            created_by=request.user
        ).order_by('-created_at')[:5]
        
        # 图表数据
        file_type_labels = json.dumps(['Excel', 'CSV', 'PDF', 'TXT', '其他'])
        file_type_data = json.dumps([15, 10, 5, 3, 2])
        trend_labels = json.dumps(['周一', '周二', '周三', '周四', '周五', '周六', '周日'])
        completed_tasks = json.dumps([12, 19, 3, 5, 2, 8, 15])
        failed_tasks = json.dumps([2, 3, 1, 0, 1, 2, 1])
        
        context = {
            'stats': {
                'total_templates': template_stats['total'],
                'total_files': file_stats['total'],
                'total_tasks': task_stats['total'],
                'pending_tasks': task_stats['pending'],
                'templates_growth': 15,
                'files_growth': 25,
                'uptime': '7天 12小时',
                'storage_used': '2.5 GB',
                'memory_used': '65%',
                'last_updated': '刚刚'
            },
            'recent_tasks': recent_tasks,
            'file_type_labels': file_type_labels,
            'file_type_data': file_type_data,
            'trend_labels': trend_labels,
            'completed_tasks': completed_tasks,
            'failed_tasks': failed_tasks
        }
        
        return render(request, 'dashboard/dashboard.html', context)
        
    except Exception as e:
        logger.error(f"Dashboard页面加载失败: {str(e)}")
        # 返回默认数据
        context = {
            'stats': {
                'total_templates': 0,
                'total_files': 0,
                'total_tasks': 0,
                'pending_tasks': 0,
                'templates_growth': 0,
                'files_growth': 0,
                'uptime': '未知',
                'storage_used': '0 MB',
                'memory_used': '0%',
                'last_updated': '未知'
            },
            'recent_tasks': [],
            'file_type_labels': json.dumps(['Excel', 'CSV', 'PDF']),
            'file_type_data': json.dumps([10, 5, 2]),
            'trend_labels': json.dumps(['周一', '周二', '周三', '周四', '周五']),
            'completed_tasks': json.dumps([12, 19, 3, 5, 2]),
            'failed_tasks': json.dumps([2, 3, 1, 0, 1])
        }
        return render(request, 'dashboard/dashboard.html', context)

@login_required
def data_upload(request):
    """数据上传页面"""
    return render(request, 'data_processing/data_upload.html')

@login_required
def task_list(request):
    """任务列表页面"""
    return render(request, 'data_processing/task_list.html')

@login_required
def task_detail(request, task_id):
    """任务详情页面"""
    task = get_object_or_404(ProcessingTask, id=task_id)
    return render(request, 'data_processing/task_detail.html', {'task': task})

@login_required
def file_manager(request):
    """文件管理页面"""
    return render(request, 'file_manager/file_manager.html')

# 模板相关视图已移至 apps.template_management.views 模块

@login_required
def data_generation(request):
    """数据生成页面"""
    return render(request, 'data_processing/data_generation.html')

# ============ API视图 ============

class FileUploadAPIView(APIView):
    """文件上传API"""
    parser_classes = (MultiPartParser, FormParser)
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        try:
            files = request.FILES.getlist('files')
            if not files:
                return Response({
                    'success': False,
                    'message': '没有选择文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 验证文件
            validation_result = data_processing_service.validate_files(files)
            if not validation_result['is_valid']:
                return Response({
                    'success': False,
                    'message': '文件验证失败',
                    'errors': validation_result['errors']
                }, status=status.HTTP_400_BAD_REQUEST)
            
            uploaded_files = []
            
            with transaction.atomic():
                for file in validation_result['valid_files']:
                    # 生成唯一文件名
                    unique_filename = generate_unique_filename(file.name)
                    
                    # 保存文件
                    file_path = default_storage.save(
                        os.path.join('uploads', unique_filename),
                        file
                    )
                    
                    # 创建文件记录
                    uploaded_file = UploadedFile.objects.create(
                        original_name=file.name,
                        file=file_path,
                        file_size=file.size,
                        file_type=os.path.splitext(file.name)[1].lower().lstrip('.'),
                        source='upload',
                        uploaded_by=request.user
                    )
                    
                    uploaded_files.append({
                        'id': uploaded_file.id,
                        'name': uploaded_file.original_name,
                        'size': uploaded_file.file_size,
                        'type': uploaded_file.file_type,
                        'url': uploaded_file.file.url if uploaded_file.file else None
                    })
                    
                    logger.info(f"用户 {request.user.username} 上传文件: {file.name}")
            
            return Response({
                'success': True,
                'message': f'成功上传 {len(uploaded_files)} 个文件',
                'files': uploaded_files
            })
            
        except Exception as e:
            logger.error(f"文件上传失败: {str(e)}")
            return Response({
                'success': False,
                'message': f'上传失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class TaskAPIView(APIView):
    """任务管理API"""
    permission_classes = [IsAuthenticated]
    
    def get(self, request, task_id=None):
        """获取任务信息"""
        try:
            if task_id:
                # 获取单个任务详情
                task = get_object_or_404(ProcessingTask, id=task_id)
                serializer = ProcessingTaskSerializer(task)
                
                # 添加额外信息
                task_data = serializer.data
                task_data['status_display'] = get_task_status_display(task.status)
                task_data['priority_display'] = get_priority_display(task.priority)
                
                # 获取关联文件
                source_files = task.source_files.all()
                result_files = task.result_files.all()
                
                task_data['source_files'] = UploadedFileSerializer(source_files, many=True).data
                task_data['result_files'] = UploadedFileSerializer(result_files, many=True).data
                
                return Response({
                    'success': True,
                    'task': task_data
                })
            else:
                # 获取任务列表
                tasks = ProcessingTask.objects.filter(created_by=request.user).order_by('-created_at')
                
                # 应用过滤条件
                status_filter = request.GET.get('status')
                if status_filter:
                    tasks = tasks.filter(status=status_filter)
                
                priority_filter = request.GET.get('priority')
                if priority_filter:
                    tasks = tasks.filter(priority=priority_filter)
                
                search = request.GET.get('search')
                if search:
                    tasks = tasks.filter(
                        Q(name__icontains=search) |
                        Q(description__icontains=search)
                    )
                
                # 分页
                page = int(request.GET.get('page', 1))
                page_size = int(request.GET.get('page_size', 20))
                
                paginator = Paginator(tasks, page_size)
                page_obj = paginator.get_page(page)
                
                serializer = ProcessingTaskSerializer(page_obj.object_list, many=True)
                
                # 添加显示信息
                tasks_data = []
                for task_data in serializer.data:
                    task_data['status_display'] = get_task_status_display(task_data['status'])
                    task_data['priority_display'] = get_priority_display(task_data['priority'])
                    tasks_data.append(task_data)
                
                return Response({
                    'success': True,
                    'tasks': tasks_data,
                    'pagination': {
                        'current_page': page_obj.number,
                        'total_pages': paginator.num_pages,
                        'total_count': paginator.count,
                        'has_next': page_obj.has_next(),
                        'has_previous': page_obj.has_previous()
                    }
                })
                
        except Exception as e:
            logger.error(f"获取任务信息失败: {str(e)}")
            return Response({
                'success': False,
                'message': f'获取任务信息失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def post(self, request):
        """创建新任务"""
        try:
            data = request.data
            
            # 验证必需字段
            required_fields = ['name', 'source_file_ids']
            for field in required_fields:
                if field not in data or not data[field]:
                    return Response({
                        'success': False,
                        'message': f'缺少必需字段: {field}'
                    }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取源文件
            source_file_ids = data['source_file_ids']
            if isinstance(source_file_ids, str):
                source_file_ids = [int(id.strip()) for id in source_file_ids.split(',') if id.strip()]
            
            source_files = UploadedFile.objects.filter(id__in=source_file_ids)
            if not source_files.exists():
                return Response({
                    'success': False,
                    'message': '没有找到有效的源文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取模板（可选）
            template = None
            template_id = data.get('template_id')
            if template_id:
                try:
                    template = Template.objects.get(id=template_id)
                except Template.DoesNotExist:
                    return Response({
                        'success': False,
                        'message': '指定的模板不存在'
                    }, status=status.HTTP_400_BAD_REQUEST)
            
            with transaction.atomic():
                # 创建任务
                task = ProcessingTask.objects.create(
                    name=data['name'],
                    description=data.get('description', ''),
                    template=template,
                    output_format=data.get('output_format', 'xlsx'),
                    priority=data.get('priority', 'normal'),
                    created_by=request.user,
                    status='pending'
                )
                
                # 关联源文件
                task.source_files.set(source_files)
                
                logger.info(f"用户 {request.user.username} 创建任务: {task.name}")
                
                # 提交任务到处理队列
                result = task_queue_service.submit_task(task)
                
                if result['success']:
                    return Response({
                        'success': True,
                        'message': '任务创建成功',
                        'task_id': task.id
                    })
                else:
                    return Response({
                        'success': False,
                        'message': f'任务提交失败: {result.get("message", "未知错误")}'
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                    
        except Exception as e:
            logger.error(f"创建任务失败: {str(e)}")
            return Response({
                'success': False,
                'message': f'创建任务失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def cancel_task(request, task_id):
    """取消任务"""
    try:
        task = get_object_or_404(ProcessingTask, id=task_id, created_by=request.user)
        
        result = task_queue_service.cancel_task(task_id)
        
        if result['success']:
            logger.info(f"用户 {request.user.username} 取消任务: {task.name}")
            return Response({
                'success': True,
                'message': '任务已取消'
            })
        else:
            return Response({
                'success': False,
                'message': result.get('message', '取消任务失败')
            }, status=status.HTTP_400_BAD_REQUEST)
            
    except Exception as e:
        logger.error(f"取消任务失败: {str(e)}")
        return Response({
            'success': False,
            'message': f'取消任务失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def retry_task(request, task_id):
    """重试任务"""
    try:
        task = get_object_or_404(ProcessingTask, id=task_id, created_by=request.user)
        
        if task.status not in ['failed', 'cancelled']:
            return Response({
                'success': False,
                'message': '只能重试失败或已取消的任务'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # 重置任务状态
        task.status = 'pending'
        task.progress = 0
        task.error_message = ''
        task.started_at = None
        task.completed_at = None
        task.save()
        
        # 重新提交任务
        result = task_queue_service.submit_task(task)
        
        if result['success']:
            logger.info(f"用户 {request.user.username} 重试任务: {task.name}")
            return Response({
                'success': True,
                'message': '任务已重新提交'
            })
        else:
            return Response({
                'success': False,
                'message': f'重试任务失败: {result.get("message", "未知错误")}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
    except Exception as e:
        logger.error(f"重试任务失败: {str(e)}")
        return Response({
            'success': False,
            'message': f'重试任务失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class FileAPIView(APIView):
    """文件管理API"""
    permission_classes = [IsAuthenticated]
    
    def get(self, request, file_id=None):
        """获取文件信息"""
        try:
            if file_id:
                # 获取单个文件信息
                file_obj = get_object_or_404(UploadedFile, id=file_id)
                serializer = UploadedFileSerializer(file_obj)
                
                file_data = serializer.data
                file_data['preview_url'] = get_file_preview_url(file_obj)
                
                return Response({
                    'success': True,
                    'file': file_data
                })
            else:
                # 获取文件列表
                files = UploadedFile.objects.all().order_by('-created_at')
                
                # 应用过滤条件
                filters = parse_file_filters(request.GET)
                if filters:
                    files = files.filter(**filters)
                
                # 分页
                page = int(request.GET.get('page', 1))
                page_size = int(request.GET.get('page_size', 20))
                
                paginator = Paginator(files, page_size)
                page_obj = paginator.get_page(page)
                
                serializer = UploadedFileSerializer(page_obj.object_list, many=True)
                
                return Response({
                    'success': True,
                    'files': serializer.data,
                    'pagination': {
                        'current_page': page_obj.number,
                        'total_pages': paginator.num_pages,
                        'total_count': paginator.count,
                        'has_next': page_obj.has_next(),
                        'has_previous': page_obj.has_previous()
                    }
                })
                
        except Exception as e:
            logger.error(f"获取文件信息失败: {str(e)}")
            return Response({
                'success': False,
                'message': f'获取文件信息失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def delete(self, request, file_id):
        """删除文件"""
        try:
            file_obj = get_object_or_404(UploadedFile, id=file_id)
            
            # 检查文件是否被任务使用
            if file_obj.source_tasks.filter(status__in=['pending', 'processing']).exists():
                return Response({
                    'success': False,
                    'message': '文件正在被任务使用，无法删除'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 删除物理文件
            if file_obj.file:
                try:
                    default_storage.delete(file_obj.file.name)
                except Exception as e:
                    logger.warning(f"删除物理文件失败: {str(e)}")
            
            file_name = file_obj.original_name
            file_obj.delete()
            
            logger.info(f"用户 {request.user.username} 删除文件: {file_name}")
            
            return Response({
                'success': True,
                'message': '文件删除成功'
            })
            
        except Exception as e:
            logger.error(f"删除文件失败: {str(e)}")
            return Response({
                'success': False,
                'message': f'删除文件失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def download_file(request, file_id):
    """下载文件"""
    try:
        file_obj = get_object_or_404(UploadedFile, id=file_id)
        
        if not file_obj.file or not default_storage.exists(file_obj.file.name):
            raise Http404("文件不存在")
        
        # 读取文件内容
        file_content = default_storage.open(file_obj.file.name, 'rb').read()
        
        # 设置响应
        response = HttpResponse(file_content)
        
        # 设置文件类型
        content_type = f'application/{file_obj.file_type}'
        if file_obj.file_type in ['txt', 'csv']:
            content_type = 'text/plain'
        elif file_obj.file_type in ['xlsx', 'xls']:
            content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        
        response['Content-Type'] = content_type
        
        # 设置下载文件名
        safe_filename = sanitize_filename_for_download(file_obj.original_name)
        response['Content-Disposition'] = f'attachment; filename="{safe_filename}"'
        
        logger.info(f"用户 {request.user.username} 下载文件: {file_obj.original_name}")
        
        return response
        
    except Exception as e:
        logger.error(f"下载文件失败: {str(e)}")
        return JsonResponse({
            'success': False,
            'message': f'下载文件失败: {str(e)}'
        }, status=500)

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def preview_file(request, file_id):
    """预览文件内容"""
    try:
        file_obj = get_object_or_404(UploadedFile, id=file_id)
        
        if not file_obj.file or not default_storage.exists(file_obj.file.name):
            return Response({
                'success': False,
                'message': '文件不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        
        # 获取预览数据
        file_path = file_obj.file.path
        preview_data = data_processing_service.preview_file(file_path)
        
        return Response({
            'success': True,
            'preview': preview_data
        })
        
    except Exception as e:
        logger.error(f"预览文件失败: {str(e)}")
        return Response({
            'success': False,
            'message': f'预览文件失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def dashboard_stats(request):
    """获取仪表板统计数据"""
    try:
        # 任务统计
        task_stats = ProcessingTask.objects.filter(created_by=request.user).aggregate(
            total=Count('id'),
            pending=Count('id', filter=Q(status='pending')),
            processing=Count('id', filter=Q(status='processing')),
            completed=Count('id', filter=Q(status='completed')),
            failed=Count('id', filter=Q(status='failed'))
        )
        
        # 文件统计
        file_stats = UploadedFile.objects.aggregate(
            total=Count('id'),
            uploads=Count('id', filter=Q(source='upload')),
            results=Count('id', filter=Q(source='result'))
        )
        
        # 模板统计
        template_stats = Template.objects.aggregate(
            total=Count('id')
        )
        
        # 最近任务
        recent_tasks = ProcessingTask.objects.filter(
            created_by=request.user
        ).order_by('-created_at')[:5]
        
        recent_tasks_data = []
        for task in recent_tasks:
            task_data = ProcessingTaskSerializer(task).data
            task_data['status_display'] = get_task_status_display(task.status)
            recent_tasks_data.append(task_data)
        
        return Response({
            'success': True,
            'stats': {
                'tasks': task_stats,
                'files': file_stats,
                'templates': template_stats
            },
            'recent_tasks': recent_tasks_data
        })
        
    except Exception as e:
        logger.error(f"获取仪表板统计失败: {str(e)}")
        return Response({
            'success': False,
            'message': f'获取统计数据失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def template_list(request):
    """获取模板列表"""
    try:
        templates = Template.objects.filter(is_active=True).order_by('-created_at')
        
        # 应用搜索过滤
        search = request.GET.get('search')
        if search:
            templates = templates.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search)
            )
        
        # 应用分类过滤
        category = request.GET.get('category')
        if category:
            templates = templates.filter(category=category)
        
        serializer = TemplateSerializer(templates, many=True)
        
        return Response({
            'success': True,
            'templates': serializer.data
        })
        
    except Exception as e:
        logger.error(f"获取模板列表失败: {str(e)}")
        return Response({
            'success': False,
            'message': f'获取模板列表失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)